package com.jacen.etl.services;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jacen.etl.util.NHibernateUtil;

public class ServiceProxyFactory implements MethodInterceptor{
	 private Enhancer enhancer = new Enhancer();
	 private Logger logger = LoggerFactory.getLogger(ServiceProxyFactory.class);

	 public Object createProxyIntance(Class<?> clazz){
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
	    return enhancer.create();
	 }

	 public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable{
		String methodStr = null; 
	    if (method.getName().equalsIgnoreCase("finalize") || method.getName().equalsIgnoreCase("getDao")) 
	    	return methodProxy.invokeSuper(obj, args);
	    try{
	       logger.debug("进入{}类{}方法", obj.getClass().getSuperclass().getName(), method.getName());
	       if (methodStr == null) {
	          methodStr = method.toString();
	       }
	       if (method.toString().equals(methodStr)) {
	          NHibernateUtil.beginTransaction();
	       }
	       Object result = methodProxy.invokeSuper(obj, args);
	       if (method.toString().equals(methodStr)) {
	          logger.debug("{}类{}方法提交", obj.getClass().getSuperclass().getName(), method.getName());
	          NHibernateUtil.commitTransaction();
	      }
	      return result;
	    } catch (Exception e) {
	    	  NHibernateUtil.rollbackTransaction();
	          throw e;
	    } finally {
	          logger.debug("退出{}类{}方法", obj.getClass().getSuperclass().getName(), method.getName());
        	  if (method.toString().equals(methodStr)) {
    	    	  NHibernateUtil.closeSession();
    	          methodStr = null;
        	  }    
	    }
	  }
	
	  @SuppressWarnings("unchecked")
	  public static <T> T createProxy(Class<T> clazz){
	    ServiceProxyFactory factory = new ServiceProxyFactory();
	    return (T)factory.createProxyIntance(clazz);
	  }
}